﻿# -*-coding: UTF-8 -*-

from PyQt5.QtCore import QTimer, Qt, QPropertyAnimation, pyqtProperty, QEasingCurve, QRectF
from PyQt5.QtGui import QPixmap, QColor, QPainter, QLinearGradient, QPen, QPainterPath, QFont
from PyQt5.QtWidgets import (
	QVBoxLayout, QLabel, QProgressBar, QSplashScreen,
	QHBoxLayout, QWidget, QPushButton, QFrame, QApplication
)


# =============================================================================
# 基础抽象工厂类
# =============================================================================

class StyleFactory:
	"""样式工厂基类"""

	def get_color(self, color_name):
		raise NotImplementedError

	def get_font_style(self, font_type):
		raise NotImplementedError

	def get_shadow_style(self, shadow_type):
		raise NotImplementedError


class WidgetFactory:
	"""控件工厂基类"""

	def create_progress_bar(self, parent=None):
		raise NotImplementedError

	def create_card(self, parent=None, elevation="small", radius=8):
		raise NotImplementedError

	def create_button(self, text="", parent=None, variant="contained", color="primary", size="medium"):
		raise NotImplementedError


class StyleSystem:
	"""样式系统基类"""

	def create_window_style(self, background_color="surface", radius=12, shadow="medium"):
		raise NotImplementedError

	def create_label_style(self, text_color="text_primary", font_type="body1", alignment="left"):
		raise NotImplementedError

	def create_button_style(self, variant="contained", color="primary", size="medium", radius=4):
		raise NotImplementedError

	def create_progress_bar_style(self, background_color="surface_light", progress_color="primary"):
		raise NotImplementedError

	def create_card_style(self, background_color="surface", radius=8, shadow="small", padding=16):
		raise NotImplementedError


# =============================================================================
# Material Design 具体实现
# =============================================================================

class MaterialStyleFactory(StyleFactory):
	"""Material Design 样式工厂"""

	# 颜色定义 - Material Design 颜色系统
	COLORS = {
		# 主色调
		"primary": "#2196F3",
		"primary_light": "#64B5F6",
		"primary_dark": "#1976D2",

		# 辅助色
		"secondary": "#FF4081",
		"secondary_light": "#FF79B0",
		"secondary_dark": "#C60055",

		# 背景色
		"background": "#121212",
		"surface": "#1E1E1E",
		"surface_light": "#2D2D2D",

		# 文本颜色
		"text_primary": "#FFFFFF",
		"text_secondary": "#B3B3B3",
		"text_hint": "#666666",
		"text_disabled": "#4D4D4D",

		# 错误和状态颜色
		"error": "#CF6679",
		"success": "#4CAF50",
		"warning": "#FF9800",
		"info": "#2196F3",

		# 其他Material颜色
		"purple": "#BB86FC",
		"teal": "#03DAC6",
		"cyan": "#18FFFF",
		"light_blue": "#00B0FF",
		"cyan_a400": "#00E5FF",
	}

	# 字体定义
	FONTS = {
		"h1": ("Segoe UI", 24, QFont.Bold),
		"h2": ("Segoe UI", 20, QFont.Bold),
		"h3": ("Segoe UI", 16, QFont.Bold),
		"h4": ("Segoe UI", 14, QFont.Bold),
		"body1": ("Segoe UI", 14, QFont.Normal),
		"body2": ("Segoe UI", 12, QFont.Normal),
		"caption": ("Segoe UI", 10, QFont.Normal),
		"button": ("Segoe UI", 14, QFont.Medium),
	}

	# 阴影定义
	SHADOWS = {
		"none": "",
		"small": "box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);",
		"medium": "box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);",
		"large": "box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);",
		"xlarge": "box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);",
	}

	def get_color(self, color_name):
		"""获取颜色"""
		return self.COLORS.get(color_name, "#000000")

	def get_font_style(self, font_type):
		"""获取字体样式"""
		font_config = self.FONTS.get(font_type, ("Segoe UI", 12, QFont.Normal))
		return f"font-family: {font_config[0]}; font-size: {font_config[1]}px; font-weight: {font_config[2]};"

	def get_shadow_style(self, shadow_type):
		"""获取阴影样式"""
		return self.SHADOWS.get(shadow_type, "")


class MaterialWidgetFactory(WidgetFactory):
	"""Material Design 控件工厂"""

	def __init__(self, style_factory):
		self.style_factory = style_factory

	def create_progress_bar(self, parent=None):
		return MaterialProgressBar(parent, self.style_factory)

	def create_card(self, parent=None, elevation="small", radius=8):
		card = MaterialCard(parent, self.style_factory)
		card.setStyleSheet(
			self.style_factory.create_card_style(
				shadow=elevation,
				radius=radius
			)
		)
		return card

	def create_button(self, text="", parent=None, variant="contained", color="primary", size="medium"):
		button = MaterialButton(text, parent, self.style_factory)
		button.setStyleSheet(
			self.style_factory.create_button_style(
				variant=variant,
				color=color,
				size=size
			)
		)
		return button


class MaterialStyleSystem(StyleSystem):
	"""Material Design 样式系统"""

	def __init__(self, style_factory):
		self.style_factory = style_factory

	def create_window_style(self, background_color="surface", radius=12, shadow="medium"):
		"""创建窗口样式"""
		return f"""
            QSplashScreen {{
                background-color: {self.style_factory.get_color(background_color)};
                border-radius: {radius}px;
                {self.style_factory.get_shadow_style(shadow)}
            }}
        """

	def create_label_style(self, text_color="text_primary", font_type="body1", alignment="left"):
		"""创建标签样式"""
		align_map = {
			"left": "left",
			"center": "center",
			"right": "right"
		}
		return f"""
            QLabel {{
                background-color: transparent;
                color: {self.style_factory.get_color(text_color)};
                {self.style_factory.get_font_style(font_type)}
                text-align: {align_map.get(alignment, "left")};
            }}
        """

	def create_button_style(self, variant="contained", color="primary", size="medium", radius=4):
		"""创建按钮样式"""
		size_map = {
			"small": "padding: 6px 12px; font-size: 12px;",
			"medium": "padding: 8px 16px; font-size: 14px;",
			"large": "padding: 12px 24px; font-size: 16px;"
		}

		if variant == "contained":
			return f"""
                QPushButton {{
                    background-color: {self.style_factory.get_color(color)};
                    color: white;
                    border: none;
                    border-radius: {radius}px;
                    {size_map.get(size, size_map["medium"])}
                    {self.style_factory.get_font_style("button")}
                    {self.style_factory.get_shadow_style("small")}
                }}
                QPushButton:hover {{
                    background-color: {self.style_factory.get_color(color + "_light")};
                }}
                QPushButton:pressed {{
                    background-color: {self.style_factory.get_color(color + "_dark")};
                }}
                QPushButton:disabled {{
                    background-color: {self.style_factory.get_color("text_disabled")};
                    color: {self.style_factory.get_color("text_hint")};
                }}
            """
		elif variant == "outlined":
			return f"""
                QPushButton {{
                    background-color: transparent;
                    color: {self.style_factory.get_color(color)};
                    border: 1px solid {self.style_factory.get_color(color)};
                    border-radius: {radius}px;
                    {size_map.get(size, size_map["medium"])}
                    {self.style_factory.get_font_style("button")}
                }}
                QPushButton:hover {{
                    background-color: {self.style_factory.get_color(color)}20;
                }}
                QPushButton:pressed {{
                    background-color: {self.style_factory.get_color(color)}40;
                }}
                QPushButton:disabled {{
                    color: {self.style_factory.get_color("text_disabled")};
                    border-color: {self.style_factory.get_color("text_disabled")};
                }}
            """
		else:  # text variant
			return f"""
                QPushButton {{
                    background-color: transparent;
                    color: {self.style_factory.get_color(color)};
                    border: none;
                    border-radius: {radius}px;
                    {size_map.get(size, size_map["medium"])}
                    {self.style_factory.get_font_style("button")}
                }}
                QPushButton:hover {{
                    background-color: {self.style_factory.get_color("text_primary")}10;
                }}
                QPushButton:pressed {{
                    background-color: {self.style_factory.get_color("text_primary")}20;
                }}
                QPushButton:disabled {{
                    color: {self.style_factory.get_color("text_disabled")};
                }}
            """

	def create_progress_bar_style(self, background_color="surface_light", progress_color="primary"):
		"""创建进度条样式"""
		return f"""
            QProgressBar {{
                border: none;
                border-radius: 3px;
                text-align: center;
                background-color: {self.style_factory.get_color(background_color)};
                height: 6px;
            }}
            QProgressBar::chunk {{
                border-radius: 3px;
                background-color: {self.style_factory.get_color(progress_color)};
            }}
        """

	def create_card_style(self, background_color="surface", radius=8, shadow="small", padding=16):
		"""创建卡片样式"""
		return f"""
            QFrame {{
                background-color: {self.style_factory.get_color(background_color)};
                border-radius: {radius}px;
                {self.style_factory.get_shadow_style(shadow)}
                padding: {padding}px;
            }}
        """


# =============================================================================
# Material Design 自定义控件
# =============================================================================

class MaterialProgressBar(QWidget):
	"""Material Design风格的进度条"""

	def __init__(self, parent=None, style_factory=None):
		super().__init__(parent)
		self.style_factory = style_factory or MaterialStyleFactory()
		self._value = 0.0
		self._maximum = 100.0
		self._minimum = 0.0
		self._animation_value = 0.0  # 用于动画的当前值

		# 创建动画
		self.animation = QPropertyAnimation(self, b"animation_value")
		self.animation.setDuration(800)
		self.animation.setEasingCurve(QEasingCurve.OutCubic)

		self.setFixedHeight(6)

	@pyqtProperty(float)
	def animation_value(self):
		return self._animation_value

	@animation_value.setter
	def animation_value(self, value):
		self._animation_value = value
		self.update()

	def setValue(self, value):
		# 修复进度条没有变化的bug - 确保值在有效范围内
		new_value = max(self._minimum, min(value, self._maximum))
		if abs(new_value - self._value) > 0.01:  # 只有值有变化时才启动动画
			self._value = new_value
			# 启动动画
			self.animation.stop()
			self.animation.setStartValue(self._animation_value)
			self.animation.setEndValue(self._value)
			self.animation.start()

	def value(self):
		return self._value

	def setRange(self, minimum, maximum):
		self._minimum = minimum
		self._maximum = maximum

	def paintEvent(self, event):
		painter = QPainter(self)
		painter.setRenderHint(QPainter.Antialiasing)

		# 计算进度百分比 (0.0 - 1.0)
		progress = (self._animation_value - self._minimum) / (self._maximum - self._minimum)

		# 绘制背景
		bg_rect = QRectF(0, 0, self.width(), self.height())
		bg_rect.adjust(0.5, 0.5, -0.5, -0.5)  # 避免抗锯齿导致的模糊边缘

		painter.setPen(Qt.NoPen)
		painter.setBrush(QColor(self.style_factory.get_color("surface_light")))
		painter.drawRoundedRect(bg_rect, 3, 3)

		# 绘制进度 - 修复进度条绘制问题
		if progress > 0:
			progress_width = self.width() * progress

			# 创建渐变
			gradient = QLinearGradient(0, 0, progress_width, 0)
			gradient.setColorAt(0.0, QColor(self.style_factory.get_color("light_blue")))
			gradient.setColorAt(0.5, QColor(self.style_factory.get_color("cyan_a400")))
			gradient.setColorAt(1.0, QColor(self.style_factory.get_color("cyan")))

			progress_rect = QRectF(0, 0, progress_width, self.height())
			progress_rect.adjust(0.5, 0.5, -0.5, -0.5)

			painter.setBrush(gradient)
			painter.drawRoundedRect(progress_rect, 3, 3)

			# 添加光泽效果 - 在进度条顶部添加一条细的白色透明条
			if progress_width > 10:  # 只在有足够宽度时绘制光泽
				highlight_rect = QRectF(0, 0, progress_width, self.height() * 0.3)
				painter.setBrush(QColor(255, 255, 255, 80))  # 半透明白色
				painter.drawRoundedRect(highlight_rect, 3, 3)


class MaterialCard(QFrame):
	"""Material Design 卡片组件"""

	def __init__(self, parent=None, style_factory=None):
		super().__init__(parent)
		self.style_factory = style_factory or MaterialStyleFactory()


class MaterialButton(QPushButton):
	"""Material Design 按钮组件"""

	def __init__(self, text="", parent=None, style_factory=None):
		super().__init__(text, parent)
		self.style_factory = style_factory or MaterialStyleFactory()


# =============================================================================
# WindowStyleSystem - 主系统类
# =============================================================================

class WindowStyleSystem:
	"""窗口样式系统 - 抽象工厂模式的入口点"""

	def __init__(self, theme="material"):
		self.theme = theme
		self.style_factory = None
		self.widget_factory = None
		self.style_system = None

		self._setup_theme(theme)

	def _setup_theme(self, theme):
		"""设置主题"""
		if theme == "material":
			self.style_factory = MaterialStyleFactory()
			self.widget_factory = MaterialWidgetFactory(self.style_factory)
			self.style_system = MaterialStyleSystem(self.style_factory)
		# 可以在这里添加其他主题，例如：
		# elif theme == "light":
		#     self.style_factory = LightStyleFactory()
		#     self.widget_factory = LightWidgetFactory(self.style_factory)
		#     self.style_system = LightStyleSystem(self.style_factory)
		else:
			raise ValueError(f"Unsupported theme: {theme}")

	def set_theme(self, theme):
		"""切换主题"""
		self._setup_theme(theme)

	# =========================================================================
	# 样式系统代理方法
	# =========================================================================

	def create_window_style(self, background_color="surface", radius=12, shadow="medium"):
		return self.style_system.create_window_style(background_color, radius, shadow)

	def create_label_style(self, text_color="text_primary", font_type="body1", alignment="left"):
		return self.style_system.create_label_style(text_color, font_type, alignment)

	def create_button_style(self, variant="contained", color="primary", size="medium", radius=4):
		return self.style_system.create_button_style(variant, color, size, radius)

	def create_progress_bar_style(self, background_color="surface_light", progress_color="primary"):
		return self.style_system.create_progress_bar_style(background_color, progress_color)

	def create_card_style(self, background_color="surface", radius=8, shadow="small", padding=16):
		return self.style_system.create_card_style(background_color, radius, shadow, padding)

	# =========================================================================
	# 控件工厂代理方法
	# =========================================================================

	def create_progress_bar(self, parent=None):
		return self.widget_factory.create_progress_bar(parent)

	def create_card(self, parent=None, elevation="small", radius=8):
		return self.widget_factory.create_card(parent, elevation, radius)

	def create_button(self, text="", parent=None, variant="contained", color="primary", size="medium"):
		return self.widget_factory.create_button(text, parent, variant, color, size)

	# =========================================================================
	# 样式工厂代理方法
	# =========================================================================

	def get_color(self, color_name):
		return self.style_factory.get_color(color_name)

	def get_font_style(self, font_type):
		return self.style_factory.get_font_style(font_type)

	def get_shadow_style(self, shadow_type):
		return self.style_factory.get_shadow_style(shadow_type)


# =============================================================================
# 使用 WindowStyleSystem 的 SplashWindow
# =============================================================================

class SplashWindow(QSplashScreen):

	def __init__(self, pixmap=None, style_system=None):
		if pixmap is None:
			# 创建一个默认的splash图像 - Material Design 深色主题
			pixmap = QPixmap(1280, 960)
			pixmap.fill(QColor(style_system.get_color("background") if style_system else "#121212"))
		super().__init__(pixmap)

		# 使用样式系统
		self.style_system = style_system or WindowStyleSystem()

		self.get_progress_function = None
		self.get_progress_name_function = None
		self.update_timer = QTimer()
		self.update_timer.timeout.connect(self.update_progress_from_callback)
		self._progress = 0.0

		# 创建平滑动画
		self.smooth_animation = QPropertyAnimation(self, b"progress")
		self.smooth_animation.setDuration(600)  # 更短的动画时间
		self.smooth_animation.setEasingCurve(QEasingCurve.OutCubic)

		self.setup_ui()

	def setup_ui(self):
		# 创建主布局
		main_layout = QVBoxLayout()
		main_layout.setContentsMargins(40, 40, 40, 40)
		main_layout.setSpacing(20)

		# 添加顶部弹性空间
		main_layout.addStretch(2)

		# 应用图标/Logo区域
		self.logo_container = QVBoxLayout()
		self.logo_container.setAlignment(Qt.AlignCenter)

		# 模拟Logo的圆形容器
		self.logo_circle = QLabel()
		self.logo_circle.setFixedSize(80, 80)
		self.logo_circle.setStyleSheet(
			f"""
            QLabel {{
                background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                    stop:0 {self.style_system.get_color("purple")}, 
                    stop:0.5 {self.style_system.get_color("teal")}, 
                    stop:1 {self.style_system.get_color("error")});
                border-radius: 40px;
                color: white;
                font-size: 32px;
                font-weight: bold;
                qproperty-alignment: AlignCenter;
            }}
            """
		)
		self.logo_circle.setText("CE")
		self.logo_container.addWidget(self.logo_circle)

		main_layout.addLayout(self.logo_container)

		# 标题标签 - Material Design 风格
		self.title_label = QLabel("Clover Engine")
		self.title_label.setAlignment(Qt.AlignCenter)
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.title_label.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_primary",
				font_type="h1",
				alignment="center"
			) + " QLabel { background-color: transparent; }"
		)

		# 副标题
		self.subtitle_label = QLabel("Professional Game Development Suite")
		self.subtitle_label.setAlignment(Qt.AlignCenter)
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.subtitle_label.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_secondary",
				font_type="body2",
				alignment="center"
			) + " QLabel { background-color: transparent; }"
		)

		main_layout.addWidget(self.title_label)
		main_layout.addWidget(self.subtitle_label)

		# 添加弹性空间
		main_layout.addStretch(1)

		# 进度条容器
		progress_container = QVBoxLayout()
		progress_container.setSpacing(8)

		# 状态标签
		self.status_label = QLabel("Initializing application...")
		self.status_label.setAlignment(Qt.AlignCenter)
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.status_label.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_secondary",
				font_type="body2",
				alignment="center"
			) + " QLabel { background-color: transparent; }"
		)

		# 使用样式系统创建自定义Material Design进度条
		self.progress_bar = self.style_system.create_progress_bar()
		self.progress_bar.setRange(0, 100)

		# 进度百分比标签
		progress_text_layout = QHBoxLayout()
		progress_text_layout.setContentsMargins(0, 0, 0, 0)

		self.progress_percent = QLabel("0%")
		self.progress_percent.setAlignment(Qt.AlignRight)
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.progress_percent.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_secondary",
				font_type="caption"
			) + " QLabel { background-color: transparent; }"
		)

		progress_text_layout.addWidget(QLabel(""))  # 占位
		progress_text_layout.addWidget(self.progress_percent)

		progress_container.addLayout(progress_text_layout)
		progress_container.addWidget(self.progress_bar)
		progress_container.addWidget(self.status_label)

		main_layout.addLayout(progress_container)

		# 底部信息区域
		bottom_layout = QHBoxLayout()

		# 版权信息
		self.copyright_label = QLabel("© 2023 Clover Studio. All rights reserved.")
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.copyright_label.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_hint",
				font_type="caption"
			) + " QLabel { background-color: transparent; }"
		)

		# 版本标签
		self.version_label = QLabel("Version 1.0.0")
		self.version_label.setAlignment(Qt.AlignRight)
		# 修复纯黑色背景与label浅色背景冲突 - 添加透明背景
		self.version_label.setStyleSheet(
			self.style_system.create_label_style(
				text_color="text_hint",
				font_type="caption"
			) + " QLabel { background-color: transparent; }"
		)

		bottom_layout.addWidget(self.copyright_label)
		bottom_layout.addWidget(self.version_label)

		main_layout.addLayout(bottom_layout)

		# 设置布局
		self.setLayout(main_layout)

		# 设置窗口属性
		# noinspection PyTypeChecker
		self.setWindowFlags(Qt.SplashScreen | Qt.FramelessWindowHint)
		# noinspection PyTypeChecker
		self.setAttribute(Qt.WA_TranslucentBackground, True)  # 启用透明背景

		# 应用窗口样式
		self.setStyleSheet(
			self.style_system.create_window_style(
				background_color="surface",
				radius=12,
				shadow="medium"
			)
		)

	def start_splash(self, get_progress_function, get_progress_name_function):
		# 每30ms更新一次进度，更高的更新频率
		self.get_progress_function = get_progress_function
		self.get_progress_name_function = get_progress_name_function
		self.update_timer.start(30)  # 更高的更新频率

	def stop_splash(self):
		self.update_timer.stop()

	@pyqtProperty(float)
	def progress(self):
		return self._progress

	@progress.setter
	def progress(self, value):
		self._progress = value
		# 修复进度条没有变化的bug - 直接设置进度条的值，不依赖动画
		self.progress_bar.setValue(value)
		self.progress_percent.setText(f"{int(value)}%")

	def update_progress_from_callback(self):
		"""从回调函数获取进度并更新"""
		if self.get_progress_function:
			progress = self.get_progress_function()
		else:
			progress = 0

		if self.get_progress_name_function:
			status_text = self.get_progress_name_function()
		else:
			status_text = "Loading"

		if status_text:
			self.status_label.setText(status_text)

		# 使用动画平滑更新进度
		self.smooth_animation.stop()
		self.smooth_animation.setStartValue(self._progress)
		self.smooth_animation.setEndValue(progress)
		self.smooth_animation.start()

	def close_splash(self):
		"""关闭splash"""
		self.update_timer.stop()
		self.close()
